package com.example.lt.service.audit;

import com.example.lt.config.QiNiuConfig;
import com.example.lt.constant.AuditStatus;
import com.example.lt.entity.response.AuditResponse;
import com.example.lt.entity.video.Video;
import com.example.lt.entity.video.VideoTask;
import com.example.lt.mapper.video.VideoMapper;
import com.example.lt.service.FeedService;
import com.example.lt.service.FileService;
import com.example.lt.service.InterestPushService;
import com.example.lt.service.user.FollowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author 小涛Tao
 * @Date: 2024/08/05/16:57
 * version 1.0 注释：
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class VideoPublishAuditServiceImpl implements AuditService<VideoTask,VideoTask>, InitializingBean {

    private final InterestPushService interestPushService;

    private final VideoMapper videoMapper;

    private final FeedService feedService;

    private final TextAuditService textAuditService;

    private final ImageAuditService imageAuditService;

    private final VideoAuditService videoAuditService;

    private final FollowService followService;

    private final FileService fileService;

    private int corePoolSizes = 5;

    // 线程池最大线程数
    private int maximumPoolSize = 8;

    // 线程池
    protected ThreadPoolExecutor executor;

    /**
     * 发布或修改视频时进行审核的方法
     * @param videoTask
     * @param auditQueueState
     * @return
     */
    public VideoTask audit(VideoTask videoTask, Boolean auditQueueState) {
        // 如果 auditQueueState 是 true 则新开一个线程来执行审核
        // TODO 这里的新建线程和提交线程池需要再改一下
        if (auditQueueState && executor.getActiveCount() < corePoolSizes) {
            new Thread(() -> {
                audit(videoTask);
            }).start();
        } else {
            audit(videoTask);
        }
        return null;
    }

    @Override
    public VideoTask audit(VideoTask videoTask) {
        executor.submit(() ->{
            final Video video = videoTask.getVideo();
            final Video video1 = new Video();
            BeanUtils.copyProperties(video, video1);
            // 只有视频是新增的或者公开的时候才需要审核视频和封面
            // 新增 ： 必须审核
            // 修改: 新老状态不一致
            // 需要审核视频/封面
            boolean needAuditVideo = false;
            // 新增视频，且新老状态一致
            if (videoTask.getIsAdd() && videoTask.getNewState() == videoTask.getOldState()) {
                needAuditVideo = true;
            } else if (!videoTask.getIsAdd() && videoTask.getNewState() != videoTask.getOldState()) {
                // 修改的情况下新老状态不一致，说明需要更新
                if (!videoTask.getNewState()) {
                    // 只有当新老状态不一致，且新状态为公开才需要审核
                    needAuditVideo = true;
                }
            }

            AuditResponse videoAuditResponse = new AuditResponse(AuditStatus.SUCCESS,"正常");
            AuditResponse coverAuditResponse = new AuditResponse(AuditStatus.SUCCESS,"正常");
            AuditResponse titleAuditResponse = new AuditResponse(AuditStatus.SUCCESS,"正常");
            AuditResponse descAuditResponse = new AuditResponse(AuditStatus.SUCCESS,"正常");

            // TODO 这里的推送还需要再改一下，是要等审核通过后才推送还是怎么样？
            if (needAuditVideo) {
                videoAuditResponse = videoAuditService.audit(QiNiuConfig.CNAME+"/"+fileService.getById(video.getUrl()).getFileKey());
                // 这个 QiNiuConfig.CNAME+"/"+fileService.getById(video.getCover()).getFileKey() 生成七牛云上图片资源的url地址，传递给audit()方法进行审核
                coverAuditResponse = imageAuditService.audit(QiNiuConfig.CNAME+"/"+fileService.getById(video.getCover()).getFileKey());

                // 将video添加到系统库中
                interestPushService.pushSystemStockIn(video1);
                interestPushService.pushSystemTypeStockIn(video1);

                // 推入发件箱
                feedService.pusOutBoxFeed(video.getUserId(), video.getId(), video1.getGmtCreated().getTime());
            } else if (videoTask.getNewState()) {
                // 删除系统库中的视频id
                interestPushService.deleteSystemStockIn(video1);
                interestPushService.deleteSystemTypeStockIn(video1);
                // 删除用户发件箱中的视频id，以及用户粉丝收件箱中的视频id
                final Collection<Long> fans = followService.getFans(video.getUserId(), null);
                feedService.deleteOutBoxFeed(video.getUserId(), fans, video.getId());
            }

            // 新老视频标题简介一致
            final Video oldVideo = videoTask.getOldVideo();
            // 如果新老视频标题简介不一致，需要对新的标题或简介进行审核
            if (videoTask.getIsAdd() || !video.getTitle().equals(oldVideo.getTitle())) {
                titleAuditResponse = textAuditService.audit(video.getTitle());
            }
            if (videoTask.getIsAdd() || (!video.getDescription().equals(oldVideo.getDescription()) && !ObjectUtils.isEmpty(video.getDescription()))){
                descAuditResponse = textAuditService.audit(video.getDescription());
            }

            final Integer videoAuditStatus = videoAuditResponse.getAuditStatus();
            final Integer coverAuditStatus = coverAuditResponse.getAuditStatus();
            final Integer titleAuditStatus = titleAuditResponse.getAuditStatus();
            final Integer descAuditStatus = descAuditResponse.getAuditStatus();
            boolean f1 = videoAuditStatus == AuditStatus.SUCCESS;
            boolean f2 = coverAuditStatus == AuditStatus.SUCCESS;
            boolean f3 = titleAuditStatus == AuditStatus.SUCCESS;
            boolean f4 = descAuditStatus == AuditStatus.SUCCESS;

            if (f1 && f2 && f3 && f4) {
                video1.setMsg("通过");
                video1.setAuditStatus(AuditStatus.SUCCESS);
                // 填充视频时长
            }else {
                video1.setAuditStatus(AuditStatus.PASS);
                // 避免干扰
                video1.setMsg("");
                // 因为这个审核的状态可能是 0、2、3 所以需要一个个的去判断
                if (!f1){
                    video1.setAuditStatus(videoAuditResponse.getAuditStatus());
                    video1.setMsg("视频有违规行为: "+videoAuditResponse.getMsg());
                }
                if (!f2){
                    video1.setAuditStatus(coverAuditResponse.getAuditStatus());
                    video1.setMsg(video1.getMsg()+"\n封面有违规行为: " + coverAuditResponse.getMsg());
                }
                if (!f3){
                    video1.setAuditStatus(titleAuditResponse.getAuditStatus());
                    video1.setMsg(video1.getMsg()+"\n标题有违规行为: " + titleAuditResponse.getMsg());
                }
                if (!f4){
                    video1.setAuditStatus(descAuditResponse.getAuditStatus());
                    video1.setMsg(video1.getMsg()+"\n简介有违规行为: " + descAuditResponse.getMsg());
                }
            }

            // 最终修改 video
            videoMapper.updateById(video1);

        });
        return null;
    }

    // 判断当前审核是快速还是慢速
    public boolean getAuditQueueState() {
        // 只要当前线程数小于核心线程数，那就是快速
        return executor.getActiveCount() < corePoolSizes;
    }

    /**
     * 初始化线程池
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("初始化审核任务线程池");
        executor  = new ThreadPoolExecutor(5, maximumPoolSize, 60, TimeUnit.SECONDS, new ArrayBlockingQueue(1000));
    }
}
